package com.ai.service.security.impl;

import com.ai.common.CommonResponse;
import com.ai.common.constant.RedisConstants;
import com.ai.common.exception.JeecgBootException;
import com.ai.entity.comm.page.SysBasePage;
import com.ai.entity.security.SysRole;
import com.ai.entity.security.SysUser;
import com.ai.entity.security.SysUserRoleRelation;
import com.ai.entity.security.page.UserPage;
import com.ai.mapper.security.SysUserMapper;
import com.ai.mapper.security.SysUserRoleRelationMapper;
import com.ai.model.param.ModifyUserPasswordParam;
import com.ai.model.param.SysUserParam;
import com.ai.model.param.UserParam;
import com.ai.model.vo.SysUserModel;
import com.ai.service.security.ISysUserRoleRelationService;
import com.ai.service.security.ISysUserService;

import com.ai.util.JwtUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author chen
 * @since 2023-04-04 19:46:07
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Resource
    private SysRoleServiceImpl sysRoleService;

    @Autowired
    private ISysUserRoleRelationService sysUserRoleRelationService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 根据用户名查询用户
     *
     * @param account
     * @return
     */
    @Override
    public SysUser selectByAccount(String account) {
        return baseMapper.selectByAccount(account);
    }

    public SysUser selectByName(String userName) {
        return baseMapper.selectByName(userName);
    }

    @Override
    @Transactional
    public CommonResponse<String> add(SysUserParam user) {

        CommonResponse<String> result = CommonResponse.ok();
        /**
         * 检测传入的用户信息
         */
        //获取所有的用户
        List<SysUser> sysUsers =
                baseMapper.selectList(null);
        //所有所有的账号
        if (!CollectionUtils.isEmpty(sysUsers)){
            List<String> accountCollect =
                    sysUsers.stream().map(SysUser::getAccount).collect(Collectors.toList());
            if (accountCollect.contains(user.getAccount())){
                throw new JeecgBootException("当前账号已存在，请勿重复添加！！！");
            }

            //所有的用户名
            List<String> userNamecollect =
                    sysUsers.stream().map(SysUser::getUserName).collect(Collectors.toList());
            if (userNamecollect.contains(user.getUserName())){
                throw new  JeecgBootException("当前用户名已存在，请勿重复添加！！！");
            }
        }
        //判断所添加的角色是否合法
        List<SysRole> list = sysRoleService.list();
        List<Integer> roleIdList =
                list.stream().map(SysRole::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleIdList)){
            if (!roleIdList.contains(Integer.valueOf(user.getRoleId()))){
                throw new  JeecgBootException("不允许添加非法用户！！！");
            }
        }

        //准备添加用户
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(user,sysUser);

        //对密码进行加密
        String password = new BCryptPasswordEncoder().encode(user.getPassword());
        sysUser.setPassword(password);

        //填充公共字段
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() != null) {
            String username = authentication.getName();
            SysUser operatUser = this.selectByName(username);
            if (null!=operatUser){
                sysUser.setCreateUser(operatUser.getId());
                sysUser.setUpdateUser(operatUser.getId());
            }
            // 可以根据username查询数据库获取更多用户信息
            log.info(username);
        }
        Date date = new Date();
        sysUser.setCreateTime(date);
        sysUser.setUpdateTime(date);



        //账号默认可用
        sysUser.setEnabled(true);
        //账号默认未过期
        sysUser.setNotExpired(true);
        //默认为未锁定
        sysUser.setAccountNotLocked(true);

        //新增用户
        boolean save = this.save(sysUser);

        //根据用户名去获取用户
//        SysUser savedUser = this.selectByName(sysUser.getUserName());
        SysUser savedUser = this.getOne(new QueryWrapper<SysUser>().eq("user_name", sysUser.getUserName()));
        //新增用户角色关系表
        SysUserRoleRelation sysUserRoleRelation = new SysUserRoleRelation();
        sysUserRoleRelation.setUserId(savedUser.getId());
        sysUserRoleRelation.setRoleId(Integer.valueOf(user.getRoleId()));
        sysUserRoleRelationService.save(sysUserRoleRelation);

        return result.setMsg("新增成功");
    }

    /**
     * 删除用户的同时，删除用户角色关系表
     * @param id
     * @return
     */
    @Override
    @Transactional
    public CommonResponse<String> deleteUser(Integer id) {

        CommonResponse<String> result = CommonResponse.ok();
        String msg="";

//        Integer id = user.getId();
        //更新用户关系表，保持数据一致性
        sysUserRoleRelationService.removeByUserId(id);
        //根据用户的id删除指定用户
        boolean b = this.removeById(id);
        if (b){
            msg="删除成功";
            result.setMsg(msg);
            //当用户信息更新之后，删除redis中对应的信息，  让其重新登录
            stringRedisTemplate.delete(RedisConstants.LOGIN_USER_INFO +id.toString());
            return result;
        }else {
            msg="删除失败";
            throw new JeecgBootException(msg);
        }
    }

    @Override
    @Transactional
    public CommonResponse<String> updateUser(SysUserParam user) {

        CommonResponse<String> result = CommonResponse.ok();
        /**
         * 检测传入的用户信息
         */
        //获取所有的用户
        List<SysUser> sysUsers =
                baseMapper.selectList(null);
        //所有所有的账号
        if (!CollectionUtils.isEmpty(sysUsers)){
            List<String> accountCollect =
                    sysUsers.stream().filter(SysUserParam->{
                        return !(user.getId().equals(SysUserParam.getId().toString()));
                    }).map(SysUser::getAccount).collect(Collectors.toList());
            if (accountCollect.contains(user.getAccount())){
                throw new  JeecgBootException("当前账号已存在，请勿重复添加！！！");
            }

            //所有的用户名
            List<String> userNamecollect =
                    sysUsers.stream().filter(SysUserParam->{
                        return !(user.getId().equals(SysUserParam.getId().toString()));
                    }).map(SysUser::getUserName).collect(Collectors.toList());
            if (userNamecollect.contains(user.getUserName())){
                throw new  JeecgBootException("当前用户名已存在，请勿重复添加！！！");
            }
        }
        //判断所添加的角色是否合法
        List<SysRole> list = sysRoleService.list();
        List<Integer> roleIdList =
                list.stream().map(SysRole::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleIdList)){
            if (!roleIdList.contains(Integer.valueOf(user.getRoleId()))){
                throw new  JeecgBootException("不允许添加非法用户！！！");
            }
        }

//判断是否需要对密码进行加密操作
        SysUser dbUser = this.getOne(new QueryWrapper<SysUser>()
                .eq("id", user.getId()));

        if (dbUser == null) {
            // 当前操作的用户不存在
            return CommonResponse.error("禁止修改不存在的用户");
        }

        String msg="";
        String password ="";
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(user,sysUser);
        sysUser.setPassword(dbUser.getPassword());



        //修改密码功能另起接口
//        if (  dbUser.getPassword().equals(user.getPassword())){
//            //则说明无需重复加密
//            password= user.getPassword();
//        }else {
//            //对密码进行加密
//            password = new BCryptPasswordEncoder().encode(user.getPassword());
//        }
//        sysUser.setPassword(password);
        sysUser.setId(Integer.valueOf(user.getId()));
        SysUserRoleRelation sysUserRoleRelation = sysUserRoleRelationService.getOne(new QueryWrapper<SysUserRoleRelation>()
                .eq("user_id", user.getId()));
        //更新用户角色关系
        sysUserRoleRelation.setRoleId(Integer.valueOf(user.getRoleId()));
        sysUserRoleRelationService.updateById(sysUserRoleRelation);
        //更新用户信息
        boolean b = this.updateById(sysUser);
        if (b){
            msg="更新成功";
            result.setMsg(msg);
            //当用户信息更新之后，删除redis中对应的信息，  让其重新登录
            log.debug("----------------------  清除redis缓存中的用户信息  ----------------------");
            log.debug("----------------------  用户id"+user.getId()+"    ----------------------");

            stringRedisTemplate.delete(RedisConstants.LOGIN_USER_INFO +user.getId().toString());

            return result;
        }else {
            msg="更新失败";
            throw new JeecgBootException(msg);
        }
    }

    /**
     * 处理用户登录逻辑
     * @param userParam
     * @return
     */
    @Override
    public CommonResponse login(UserParam userParam) {
//       注入 AuthenticationManager  调用authenticate 方法进行登录认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userParam.getUserName(), userParam.getPassword());

        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//       认证没有通过，给出提示-----> 返回值为null，则说明认证未通过
//       认证通过，使用userid 生成一个jwt
        User loginUser = (User) authenticate.getPrincipal();
        String account = loginUser.getUsername();
        SysUser user = this.getOne(new QueryWrapper<SysUser>().eq("account", account));
        Collection<GrantedAuthority> authorities = loginUser.getAuthorities();

        List<String> permission=new ArrayList<>();
        if (!CollectionUtils.isEmpty(authorities)){
            ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            grantedAuthorities.addAll(authorities);
            user.setGrantedAuthorities(grantedAuthorities);
            permission = user.getGrantedAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
        }
        String token = JwtUtil.createJWT(user.getId().toString());



        HashMap<String, Object> map = new HashMap<>();
        map.put("userName",user.getUserName());
        map.put("token",token);
        map.put("authorities",permission);
        //  讲完整的用户信息存储在redis中
        stringRedisTemplate.opsForValue().set(RedisConstants.LOGIN_USER_INFO +user.getId().toString(), JSON.toJSONString(user));
        return  CommonResponse.ok("登录成功",map);
    }

    /**
     * 分页查询
     * @param page
     * @return
     */
    @Override
    public IPage<SysUserModel> getList(UserPage page) {
        // 根据创建时间排序
        QueryWrapper<SysUser> queryWrapper = page.getQuery(new QueryWrapper<>()).orderByDesc("create_time");
        queryWrapper.select(SysUser.class,item->!item.getColumn().equals("password"));
        IPage<SysUser> userPage = this.page(page, queryWrapper);

        List<SysUser> records = userPage.getRecords();

        ArrayList<SysUserModel> sysUserModels = new ArrayList<>();

        if (!CollectionUtils.isEmpty(records)){
            for (SysUser sysUser : records) {
                SysUserModel sysUserModel = new SysUserModel();
                BeanUtils.copyProperties(sysUser,sysUserModel);
                //获取当前的角色id
                SysUserRoleRelation roleRelationServiceOne = sysUserRoleRelationService.getOne(new QueryWrapper<SysUserRoleRelation>()
                        .eq("user_id", sysUser.getId()));

                if (roleRelationServiceOne != null){
                    SysRole sysRole = sysRoleService.getOne(new QueryWrapper<SysRole>()
                            .eq("id", roleRelationServiceOne.getRoleId()));
                    if (sysRole != null){
                        sysUserModel.setRoleId(String.valueOf(sysRole.getId()));
                        sysUserModel.setRoleName(sysRole.getRoleName());
                    }
                }
                sysUserModels.add(sysUserModel);
            }
        }

        IPage<SysUserModel> sysUserModelIPage = new SysBasePage<>();
        BeanUtils.copyProperties(userPage,sysUserModelIPage);
        sysUserModelIPage.setRecords(sysUserModels);

        return sysUserModelIPage;
    }

    @Override
    public CommonResponse getUserInfoVo(String id) {

        SysUser user = this.getById(id);
        if (null==user){
            throw new JeecgBootException("该用户不存在");
        }

        SysUserModel sysUserModel = new SysUserModel();
        BeanUtils.copyProperties(user,sysUserModel);
        //获取当前的角色id
        SysUserRoleRelation roleRelationServiceOne = sysUserRoleRelationService.getOne(new QueryWrapper<SysUserRoleRelation>()
                .eq("user_id", id));
        //根据当前角色id，获取对应的角色
        SysRole sysRole = sysRoleService.getOne(new QueryWrapper<SysRole>()
                .eq("id", roleRelationServiceOne.getRoleId()));

        if (null  != sysRole){
            sysUserModel.setRoleId(String.valueOf(sysRole.getId()));
            sysUserModel.setRoleName(sysRole.getRoleName());
        }

        return CommonResponse.ok(sysUserModel);
    }

    /**
     * 修改密码
     * @param passwordParam
     * @return
     */
    @Override
    public CommonResponse<String> modifyPassword(ModifyUserPasswordParam passwordParam) {

        SysUser sysUser = this.getById(passwordParam.getId());
        String password = new BCryptPasswordEncoder().encode(passwordParam.getPassword());
        sysUser.setPassword(password);
        boolean b = this.updateById(sysUser);
        if (b){
            //当用户信息更新之后，删除redis中对应的信息，  让其重新登录
            stringRedisTemplate.delete(RedisConstants.LOGIN_USER_INFO +passwordParam.getId().toString());
            return CommonResponse.ok("密码修改成功");
        }else {
            return CommonResponse.error("密码修改失败");
        }
    }













}
